#include "qae_qcharwidget.h"
#include <QtCore/QFile>
#include <QtCore/QString>
#include <QtGui/QComboBox>
#include <QtXml/QDomDocument>
#include <QtGui/QFont>
#include <QtGui/QHeaderView>
#include <QtGui/QScrollBar>
#include <QtGui/QShowEvent>
#include <QtGui/QTableWidget>
#include <QtGui/QVBoxLayout>


namespace QAnsiEditor {


QCharWidget::QCharWidget(QWidget *parent) :
    QWidget(parent)
{
    init();
}

QSize QCharWidget::sizeHint() const
{
    // QDockWidget seems to use this value to decide its size.
    // So just return the minimum size, not the preferred size.
    return QSize(m_iPreferredWidth-6*fixedCellSize, m_iPreferredHeight);
}

// The correct size of QTableWidget is report until it is show.
// We may want to override this function to check the actual size of the table.
void QCharWidget::showEvent(QShowEvent *event)
{
    QWidget::showEvent(event);
}

bool QCharWidget::init()
{
    if (!initCharData()) {
        return false;
    }

    m_pSecCombo = new QComboBox;
    if (!initSecCombo()) {
        return false;
    }
    connect(m_pSecCombo, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(secChanged(const QString &)));

    m_pCharTable = new QTableWidget;
    if (!initCharTable("common")) {
        return false;
    }
    connect(m_pCharTable, SIGNAL(itemClicked(QTableWidgetItem *)), this, SIGNAL(charClicked(QTableWidgetItem *)));

    QVBoxLayout *mainLayout = new QVBoxLayout;
    mainLayout->setMargin(4);
    mainLayout->setSpacing(4);
    mainLayout->addWidget(m_pSecCombo);
    mainLayout->addWidget(m_pCharTable);
    setLayout(mainLayout);

    m_iPreferredWidth = fixedColumnCount*fixedCellSize + m_pCharTable->verticalScrollBar()->width() + m_pCharTable->frameWidth()*3 + layout()->margin()*2;
    m_iPreferredHeight = m_pCharTable->y() + fixedRowCount*fixedCellSize + m_pCharTable->frameWidth()*3 + layout()->margin()*2;
    setMaximumWidth(m_iPreferredWidth);
    setMinimumHeight(m_iPreferredHeight);

    return true;
}

bool QCharWidget::initCharData()
{
    if (m_charHash.isEmpty()) {
        QFile file(":/characters.xml");
        if (!file.open(QFile::ReadOnly | QFile::Text)) {
            return false;
        }
        QDomDocument doc;
        if (!doc.setContent(file.readAll())) {
            return false;
        }

        QDomNodeList groupList = doc.elementsByTagName("group");
        for (int i = 0; i < (int)groupList.length(); i++) {
            QDomElement groupElem = groupList.at(i).toElement();
            QString strKey = groupElem.attribute("name");
            QStringList strValueList;
            QDomNodeList lineList = groupElem.childNodes();
            for (int i = 0; i < (int)lineList.length(); i++) {
                QDomElement lineElem = lineList.at(i).toElement();
                if (lineElem.tagName() == "line") {
                    strValueList << lineElem.text();
                } else if (lineElem.tagName() == "separator") {
                    strValueList << QString::null;
                }
            }
            m_charHash.insert(strKey, strValueList);
        }
    }

    return true;
}

bool QCharWidget::initSecCombo()
{
    QList<QString> keys = m_charHash.keys();
    for (int i = 0; i < keys.size(); i++) {
        m_pSecCombo->addItem(keys[i]);
    }

    return true;
}

bool QCharWidget::initCharTable(const QString &strKey)
{
    m_pCharTable->clearContents();

    QStringList strValueList;
    int rowCount = fixedRowCount;
    if (m_charHash.isEmpty()) {
        // noop
    } else {
        strValueList = m_charHash.value(strKey);
        if (strValueList.isEmpty()) {
            // noop
        } else {
            int size = strValueList.size();
            rowCount = (size >= fixedRowCount) ? size : fixedRowCount;
        }
    }
    // create table
    m_pCharTable->setRowCount(rowCount);
    m_pCharTable->setColumnCount(fixedColumnCount);
    m_pCharTable->setSelectionMode(QAbstractItemView::SingleSelection);
    m_pCharTable->horizontalHeader()->hide();
    m_pCharTable->verticalHeader()->hide();
    for (int i = 0; i < m_pCharTable->rowCount(); i++) {
        m_pCharTable->setRowHeight(i, fixedCellSize);
    }
    for (int i = 0; i < m_pCharTable->columnCount(); i++) {
        m_pCharTable->setColumnWidth(i, fixedCellSize);
    }
    // set font, otherwise some character display abnormally.
    m_pCharTable->setFont(QFont("SimSun", 8));
    // set content
    if (!strValueList.isEmpty()) {
        for (int i = 0; i < strValueList.size(); i++) {
            QString strValue = strValueList.at(i);
            if (strValue != QString::null) {
                for (int j = 0; j < fixedColumnCount; j++) {
                    QTableWidgetItem *newItem = new QTableWidgetItem(strValue.at(j));
                    newItem->setTextAlignment(Qt::AlignCenter | Qt::AlignHCenter);
                    newItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
                    m_pCharTable->setItem(i, j, newItem);
                }
            }
        }
    }

    return true;
}

void QCharWidget::secChanged(const QString &text)
{
    this->initCharTable(text);
    m_pCharTable->repaint();
}


}  // namespace QAnsiEditor
